home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / MacShell / File.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-04  |  11.9 KB  |  482 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:         MacShell
  5. ** File:            file.c
  6. ** Some code from:  Traffic Light 2.0 version, by Keith Rollin & John Harvey
  7. ** Modified by:     Eric Soldan
  8. **
  9. ** Copyright © 1990-1991 Apple Computer, Inc.
  10. ** All rights reserved.
  11. */
  12.  
  13.  
  14.  
  15. /*****************************************************************************/
  16.  
  17.  
  18.  
  19. #include "MacShell.h"            /* Get the MacShell includes/typedefs, etc.    */
  20. #include "MacShellCommon.h"        /* Get the stuff in common with rez.        */
  21. #include "MacShell.protos"        /* Get the prototypes for MacShell.            */
  22.  
  23. #ifndef __ERRORS__
  24. #include <Errors.h>
  25. #endif
  26.  
  27. #ifndef __PACKAGES__
  28. #include <Packages.h>
  29. #endif
  30.  
  31. #ifndef __TOOLUTILS__
  32. #include <ToolUtils.h>
  33. #endif
  34.  
  35. #ifdef THINK_C
  36. #include "Utilities.h"
  37. #else
  38. #ifndef __UTILITIES__
  39. #include <Utilities.h>
  40. #endif
  41. #endif
  42.  
  43.  
  44.  
  45. /*****************************************************************************/
  46.  
  47.  
  48.  
  49. static Boolean    gIncNewFileNumFlag = true;
  50.  
  51.  
  52.  
  53. /*****************************************************************************/
  54. /*****************************************************************************/
  55.  
  56.  
  57.  
  58. /* This function disposes of the document.  It checks to see if a file is
  59. ** currently open for the document.  If it is, then the document is closed.
  60. ** Once there is no open file for the document, the memory occupied by the
  61. ** document is released.
  62. */
  63.  
  64. #pragma segment File
  65. OSErr    AppDisposeDocument(FileRecHndl frHndl)
  66. {
  67.     OSErr    err;
  68.  
  69.     err = noErr;
  70.  
  71.     if (frHndl) {
  72.         if ((*frHndl)->fileState.fss.vRefNum != kInvalVRefNum)
  73.             err = FSClose((*frHndl)->fileState.refNum);
  74.                 /* Close the file, if opened. */
  75.  
  76.         AppFreeDocument(frHndl);
  77.             /* Free all application-specific ram for the document. */
  78.  
  79.         DisposHandle((Handle)frHndl);
  80.             /* Release memory for the document handle. */
  81.     }
  82.  
  83.     return(err);
  84. }
  85.  
  86.  
  87.  
  88. /*****************************************************************************/
  89.  
  90.  
  91.  
  92. /* This function creates a new document.  A handle is created as the
  93. ** reference to the document.  Header information is placed in this handle.
  94. ** The application-specific data follows this header information.  The
  95. ** handle is returned (or nil upon failure), and typically the handle is
  96. ** then stored in the refCon field of the window.  Note that this is a
  97. ** convention, and is not mandatory.  This allows a document to exist that
  98. ** has no window.  A document with no window is useful when the application
  99. ** is called from the finder in response to a print request.  The document
  100. ** can be loaded and printed without involving a window on the screen.
  101. */
  102.  
  103.  
  104. #pragma segment File
  105. OSErr    AppNewDocument(FileRecHndl *returnHndl, OSType sftype)
  106. {
  107.     static short    untitledCount;
  108.     FileRecHndl        frHndl;
  109.     FileRecPtr        frPtr;
  110.     Str255            untitled;
  111.     char            *pstr;
  112.     OSErr            err;
  113.  
  114.     err = memFullErr;
  115.     if (*returnHndl = frHndl = (FileRecHndl)NewHandle(sizeof(FileRec))) {
  116.         GetIndString(untitled, rMiscStrings, sOrigName);
  117.         frPtr = *frHndl;
  118.         frPtr->fileState.sfType            = sftype;
  119.         frPtr->fileState.docDirty          = false;
  120.         frPtr->fileState.readOnly          = false;
  121.         frPtr->fileState.fss.vRefNum       = kInvalVRefNum;
  122.         frPtr->fileState.window            = nil;
  123.         frPtr->fileState.imageProc         = ImageDocument;
  124.         frPtr->fileState.contentClickProc  = ContentClick;
  125.         frPtr->fileState.contentKeyProc    = ContentKey;
  126.         frPtr->fileState.initContentProc   = InitContent;
  127.         frPtr->fileState.resizeContentProc = ResizeContent;
  128.         frPtr->fileState.drawFrameProc     = DrawFrame;
  129.         frPtr->fileState.calcFrameRgnProc  = CalcFrameRgn;
  130.         pstr = (char *)frPtr->fileState.fss.name;
  131.         pstrcpy(pstr, (char *)untitled);
  132.         if (gIncNewFileNumFlag) ++untitledCount;
  133.         appendi2pstr(pstr, untitledCount);
  134.         if (err = AppInitDocument(frHndl)) {
  135.             DisposHandle((Handle)frHndl);
  136.             *returnHndl = nil;
  137.         }
  138.     }
  139.     return(err);
  140. }
  141.  
  142.  
  143.  
  144. /*****************************************************************************/
  145.  
  146.  
  147.  
  148. #pragma segment File
  149. OSErr    AppOpenDocument(FileRecHndl *result, FSSpecPtr fileToOpen, char permission)
  150. {
  151.     StandardFileReply    reply;
  152.     short                fileRefNum;
  153.     FileRecHndl            frHndl;
  154.     OSErr                err;
  155.     FSSpec                myFileSpec;
  156.     DialogPtr            openDialog;
  157.     short                item;
  158.  
  159.     *result = nil;        /* Assume we will fail. */
  160.  
  161.     if (!fileToOpen) {
  162.         if (DisplayGetFile(&reply))        /* Let the user decide which file. */
  163.             myFileSpec = reply.sfFile;    /* User's choice.                   */
  164.         else
  165.             return(userCanceledErr);    /* User canceled. */
  166.     }
  167.     else
  168.         myFileSpec = *fileToOpen;        /* Pre-designated file to open. */
  169.  
  170.     IncNewFileNum(false);
  171.     err = AppNewDocument(&frHndl, reply.sfType);
  172.     IncNewFileNum(true);
  173.     if (err) return(err);
  174.         /* We couldn't create an empty document, so give it up. */
  175.  
  176.     err = HOpen(myFileSpec.vRefNum, myFileSpec.parID,
  177.                 myFileSpec.name, permission, &fileRefNum);
  178.  
  179.     if (err == opWrErr) {
  180.  
  181.         ParamText(myFileSpec.name, nil, nil, nil);
  182.         openDialog = GetCenteredDialog(rOpenReadOnly, nil, nil, (WindowPtr)-1L);
  183.         if (!openDialog) {
  184.             AppDisposeDocument(frHndl);
  185.             return(err);
  186.         }
  187.  
  188.         OutlineDialogItem(openDialog, kOpenYes);
  189.         DoSetCursor(&qd.arrow);
  190.         ModalDialog((ModalFilterProcPtr)keyEquivFilter, &item);
  191.         DisposDialog(openDialog);
  192.         if (item != kOpenYes) return(userCanceledErr);
  193.  
  194.         (*frHndl)->fileState.readOnly = true;
  195.         err = HOpen(myFileSpec.vRefNum, myFileSpec.parID,
  196.                     myFileSpec.name, fsRdPerm, &fileRefNum);
  197.     }
  198.  
  199.     if (err) {
  200.         AppDisposeDocument(frHndl);
  201.         return(err);
  202.     }
  203.  
  204.     (*frHndl)->fileState.fss    = myFileSpec;
  205.     (*frHndl)->fileState.refNum = fileRefNum;
  206.  
  207.     if (err = AppReadDocument(frHndl)) {
  208.         AppDisposeDocument(frHndl);
  209.         return(err);
  210.     }
  211.  
  212.     if ((*frHndl)->fileState.readOnly) {
  213.         FSClose((*frHndl)->fileState.refNum);
  214.         (*frHndl)->fileState.fss.vRefNum = kInvalVRefNum;
  215.     }        /* If it's read-only, we don't need the file left open. */
  216.  
  217.     *result = frHndl;
  218.     return(noErr);
  219. }
  220.  
  221.  
  222.  
  223. /*****************************************************************************/
  224.  
  225.  
  226.  
  227. #pragma segment File
  228. OSErr    AppSaveDocument(FileRecHndl    frHndl, WindowPtr window, short saveMode)
  229. {
  230.     Str255                closeOrQuit;
  231.     short                item;
  232.     StandardFileReply    reply;
  233.     OSErr                err;
  234.     short                fileRefNum;
  235.     DialogPtr            saveDialog;
  236.     Boolean                doPrompt;
  237.  
  238. /*    When entering, saveMode is set to the menu command number of the
  239. **    the item that prompted this. Current settings are iSave, iSaveAs,
  240. **    iClose, and iQuit.
  241. */
  242.  
  243.     if (saveMode != iSaveAs) {                        /* If regular save... */
  244.         if (!(*frHndl)->fileState.docDirty)            /* If file clean...   */
  245.             return(noErr);                            /* Consider it saved. */
  246.     }
  247.  
  248.     pstrcpy((char *)reply.sfFile.name, (char *)(*frHndl)->fileState.fss.name);
  249.  
  250.     if ((saveMode == iClose) || (saveMode == iQuit)) {
  251.         /* If implicit save... */
  252.  
  253.         GetIndString(closeOrQuit, rMiscStrings,
  254.                      (saveMode == iClose) ? sWClosing : sQuitting);
  255.         ParamText(reply.sfFile.name, closeOrQuit, nil, nil);
  256.  
  257.         saveDialog = GetCenteredDialog(rYesNoCancel, nil, window, (WindowPtr)-1L);
  258.  
  259.         if (saveDialog) {
  260.             OutlineDialogItem(saveDialog, kSaveYes);
  261.             DoSetCursor(&qd.arrow);
  262.             ModalDialog((ModalFilterProcPtr)keyEquivFilter, &item);
  263.             DisposDialog(saveDialog);
  264.         }
  265.         else
  266.             item = kSaveYes;
  267.  
  268.         if (item != kSaveYes) {
  269.             err = noErr;
  270.             if (item == kSaveCanceled) err = userCanceledErr;
  271.             return(err);
  272.         }
  273.     }
  274.  
  275.     doPrompt = (
  276.         (saveMode == iSaveAs) ||
  277.         ((*frHndl)->fileState.fss.vRefNum == kInvalVRefNum)
  278.     );
  279.  
  280.     if (doPrompt) {
  281.         /* Prompt with SFGetFile if doing a Save As or have never saved before. */
  282.  
  283.         if (!DisplayPutFile(&reply))
  284.             return(userCanceledErr);
  285.                 /* User canceled the save. */
  286.  
  287.         if ((*frHndl)->fileState.fss.vRefNum != kInvalVRefNum)
  288.             FSClose((*frHndl)->fileState.refNum);
  289.                 /* Close the old file.  Don't respond to any error here because
  290.                 ** the user may be trying to do a save-as because their old file
  291.                 ** is bad.  If we fail to close the old file, and then respond
  292.                 ** to the error, the user won't get the opportunity to save
  293.                 ** their document to a new file.
  294.                 */
  295.  
  296.         if (err = Create_OpenFile(&reply.sfFile, &fileRefNum)) {
  297.             (*frHndl)->fileState.fss.vRefNum = kInvalVRefNum;
  298.             return(err);
  299.         }
  300.  
  301.         (*frHndl)->fileState.fss    = reply.sfFile;
  302.         (*frHndl)->fileState.refNum = fileRefNum;
  303.             /* This is the new file. */
  304.  
  305.         if (window) NewWindowTitle(window);
  306.     }
  307.  
  308.     if (err = AppWriteDocument(frHndl))
  309.         return(err);
  310.  
  311.     (*frHndl)->fileState.docDirty = false;
  312.     (*frHndl)->fileState.readOnly = false;
  313.     return(noErr);
  314. }
  315.  
  316.  
  317.  
  318. /*****************************************************************************/
  319.  
  320.  
  321.  
  322. /* ConvertOldToNewSFReply
  323. **
  324. ** struct StandardFileReply {            struct SFReply {
  325. **     Boolean     sfGood;                <-    Boolean good;
  326. **     Boolean     sfReplacing;        <-    Boolean copy;
  327. **     OSType         sfType;                <-    OSType fType;
  328. **     FSSpec        sfFile;
  329. **                     vRefNum;        <-    real vRefnum from (short vRefNum)
  330. **                     parID;            <-    real dirID from (short vRefNum)
  331. **                     name;            <-    Str63 fName;
  332. **     ScriptCode    sfScript;            <-    iuSystemScript
  333. **     short         sfFlags;            <-    0
  334. **     Boolean     sfIsFolder;            <-    false
  335. **     Boolean     sfIsVolume;            <-    false
  336. **     long        sfReserved1;        <-    0
  337. **     short        sfReserved2;        <-    0
  338. ** };                                    };
  339. */
  340.  
  341. #pragma segment File
  342. void    ConvertOldToNewSFReply(SFReply *oldReply, StandardFileReply *newReply)
  343. {
  344.     OSErr        err;
  345.     long        ignoredProcID;
  346.     
  347.     newReply->sfGood        = oldReply->good;
  348.     newReply->sfReplacing    = oldReply->copy;        /* Correct assignment? */
  349.     newReply->sfType        = oldReply->fType;
  350.  
  351.     err = GetWDInfo(oldReply->vRefNum,
  352.                     &newReply->sfFile.vRefNum,
  353.                     &newReply->sfFile.parID,
  354.                     &ignoredProcID);
  355.     BlockMove((Ptr)&oldReply->fName,
  356.               (Ptr)&newReply->sfFile.name,
  357.               oldReply->fName[0]+1);
  358.  
  359.     /* Punt on the rest. */
  360.     newReply->sfScript        = iuSystemScript;
  361.     newReply->sfFlags        = 0;
  362.     newReply->sfIsFolder    = false;
  363.     newReply->sfIsVolume    = false;
  364.     newReply->sfReserved1    = 0;
  365.     newReply->sfReserved2    = 0;
  366. }
  367.  
  368.  
  369.  
  370. /*****************************************************************************/
  371.  
  372.  
  373.  
  374. /* Create_OpenFile
  375. **
  376. ** Opens the file specified by the passed FSSpec, creating it if it doesn't
  377. ** already exist. Refturns the refnum of the open file to the application.
  378. ** File Manager errors are reported and returned.
  379. */
  380.  
  381. #pragma segment File
  382. OSErr    Create_OpenFile(FSSpec *file, short *refNum)
  383. {
  384.     OSErr    err;
  385.  
  386.     err = HCreate(file->vRefNum, file->parID, file->name, docCreator, docFileType);
  387.     if (err == dupFNErr) {
  388.  
  389.         /* The user already told Standard File to replace the old file
  390.            so let's get rid of it. */
  391.  
  392.         HDelete(file->vRefNum, file->parID, file->name);
  393.  
  394.         /* Try creating it again. */
  395.         err = HCreate(file->vRefNum, file->parID, file->name, docCreator, docFileType);
  396.     }
  397.  
  398.     if (!err) {
  399.         err = HOpen(file->vRefNum, file->parID, file->name, fsRdWrPerm, refNum);
  400.         if (err)
  401.             HDelete(file->vRefNum, file->parID, file->name);
  402.     }
  403.  
  404.     return(err);
  405. }
  406.  
  407.  
  408.  
  409. /*****************************************************************************/
  410.  
  411.  
  412.  
  413. /* DisplayGetFile
  414. **
  415. ** Simple routine to display a list of files with our file type.
  416. */
  417.  
  418. #pragma segment File
  419. Boolean DisplayGetFile(StandardFileReply *reply)
  420. {
  421.     SFTypeList    typeList = {docFileType};
  422.     Point        where = {100, 100};
  423.     SFReply        oldReply;
  424.  
  425.     if (gSystemVersion >= 0x0700)        /* If new standard file available... */
  426.         StandardGetFile(nil, 1, typeList, reply);
  427.  
  428.     else {
  429.         SFGetFile(where, "\pSelect a document to open.",
  430.                          nil, 1, typeList, nil, &oldReply);
  431.         ConvertOldToNewSFReply(&oldReply, reply);
  432.     }
  433.  
  434.     return(reply->sfGood);
  435. }
  436.  
  437.  
  438.  
  439. /*****************************************************************************/
  440.  
  441.  
  442.  
  443. /* DisplayPutFile
  444. **
  445. ** Displays the StandardFile PutFile dialog box. Fills out the passed reply
  446. ** record, and returns the sfGood field as a result.
  447. */
  448.  
  449. #pragma segment File
  450. Boolean DisplayPutFile(StandardFileReply *reply)
  451. {
  452.     Str255        prompt;
  453.     Point        where = {100, 100};
  454.     SFReply        oldReply;
  455.  
  456.     GetIndString(prompt, rMiscStrings, sSFprompt);
  457.  
  458.     if (gSystemVersion >= 0x0700)    /* If new standard file available... */
  459.         StandardPutFile(prompt, reply->sfFile.name, reply);
  460.     else {
  461.         SFPutFile(where, prompt, reply->sfFile.name, nil, &oldReply);
  462.         ConvertOldToNewSFReply(&oldReply, reply);
  463.     }
  464.  
  465.     return(reply->sfGood);
  466. }
  467.  
  468.  
  469.  
  470. /*****************************************************************************/
  471.  
  472.  
  473.  
  474. #pragma segment File
  475. void    IncNewFileNum(Boolean flag)
  476. {
  477.     gIncNewFileNumFlag = flag;
  478. }
  479.  
  480.  
  481.  
  482.